package hc.bre.project

import hc.bre.cmn.RuleScriptBuilder
import hc.bre.rest.admin.BreAdminConfig
import hc.bre.rest.admin.ScriptFileMode

@groovy.transform.CompileStatic
class ProjectBuilder extends RuleScriptBuilder<ProjectDefinition>{
	@Override
	public RuleScriptBuilder forRule(ProjectDefinition ruleDef) {
		this.ruleDef = ruleDef.project;
		this.projectPackage = packageName();
		return this;
	}

	ScriptFileMode getScriptFileMode() {
		BreAdminConfig.config.scriptFileMode;
	}

	@Override
	public String build() {
		if(getScriptFileMode() ==  ScriptFileMode.allInOne) {
			return buildForAll();
		}
		else {
			return buildForSelf();
		}
	}

	String buildForAll() {
		StringBuilder mainBuilder = new StringBuilder();

		List<RuleScriptBuilder> builderList = [];

		//step 0. pre-process to get all rule's builder
		ruleDef.ruleList?.each {rule ->
			rule.project = this.ruleDef;

			RuleScriptBuilder builder =
					rule.scriptBuilderClass().getConstructor().newInstance().forRule(rule);

			//project package
			builder.projectPackage = packageName();
			builderList.add(builder);
		};

		//step 1. process to build class content for each builder
		builderList.each { builder ->
			builder.buildClass();
			//combine the import statements
			builder.classUsedMap.each { k,v->
				this.classUse(v);
			}
		};

		//step 2. combine all script into whole script
		mainBuilder.append("package ${packageName()}").append("\n");

		mainBuilder.append(TextOfImport()).append("\n");

		//step 3. append project main class
		//		mainBuilder.append(this.buildClass());
		this.buildClasRuleBody()
		mainBuilder.append(this.sbOfClass);

		//		builderList.each { builder ->
		//			mainBuilder.append(builder.sbOfClass);
		//			mainBuilder.append("\n");
		//		};
		PackClassBuilder packBuilder = new PackClassBuilder(packageNode:packageName()
		,projectPackage:projectPackage
		,packPackage:projectPackage);
		mainBuilder.append(packBuilder.buildList(builderList));

		return mainBuilder.toString();
	};

	String buildForSelf()
	{
		buildClasRuleBody();

		StringBuilder sb  = new StringBuilder();
		sb.append("package ${packageName()}");
		sb.append(TextOfImport());
		sb.append(sbOfClass);

		return sb.toString();
	}

	@Override
	public void buildClasRuleBody() {
		apdNl("switch(_entry_){");
		nested{
			ruleDef.ruleList?.each {rule ->
				apdNl("case '${rule.rpath}':").apdNl("\t return ${referApplyRule(rule)};")
			};

			//support the default entry, by project rpath or '' or null
			if(ruleDef.defaultEntry)
			{
				apdNl("case '${ruleDef.rpath}':")
				apdNl("case '':")
				apdNl("case null:")
				apdNl("\t return ${referApplyRule(ruleDef.defaultEntry)};")
			}

			apdNl('default : return "Wrong rule entry of \${_entry_} with variable [_entry_].";');
		};

		apdNl("};")
	}

}
